package com.tanhua.manage.service;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.additional.query.impl.QueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tanhua.manage.domain.AnalysisByDay;
import com.tanhua.manage.mapper.AnalysisByDayMapper;
import com.tanhua.manage.utils.ComputeUtil;
import com.tanhua.manage.vo.AnalysisSummaryVo;
import com.tanhua.manage.vo.AnalysisUsersVo;
import com.tanhua.manage.vo.DataPointVo;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 概要统计分析业务处理层
 */
@Service
public class AnalysisService extends ServiceImpl<AnalysisByDayMapper, AnalysisByDay> {

    /**
     * 首页-概要统计分析展示
     */
    public AnalysisSummaryVo summary() {
        Date date = new Date();
        DateTime today = DateUtil.date(date);//今日时间

        DateTime yesterday = DateUtil.offsetDay(date, -1); //昨天时间
        DateTime myYesterday = DateUtil.date(yesterday);

        AnalysisSummaryVo vo = new AnalysisSummaryVo();
        //SELECT SUM(num_registered) as numRegistered FROM tb_analysis_by_day;
        vo.setCumulativeUsers(queryNumRegistered());//累计用户数
        vo.setActivePassMonth(queryUserCount(today,-30,"num_active"));//过去30天活跃用户数
        vo.setActivePassWeek(queryUserCount(today,-7,"num_active"));//过去7天活跃用户

        Long todayRegistered = queryUserCount(today, 0, "num_registered");// 今日新增用户数量
        vo.setNewUsersToday(todayRegistered);//今日新增用户数量
        Long yesterdayRegistered = queryUserCount(myYesterday, 0, "num_registered");// 今日新增用户数量
        vo.setNewUsersTodayRate(ComputeUtil.computeRate(todayRegistered,yesterdayRegistered));//今日新增用户涨跌率


        Long todayNumLogin = queryUserCount(today, 0, "num_login");
        vo.setLoginTimesToday(todayNumLogin);//今日登录次数
        Long yesterdayNumLogin = queryUserCount(myYesterday, 0, "num_login");// 今日新增用户数量
        vo.setLoginTimesTodayRate(ComputeUtil.computeRate(todayNumLogin,yesterdayNumLogin));//今日登录次数涨跌率


        Long todayNumactive = queryUserCount(today, 0, "num_active");
        vo.setActiveUsersToday(todayNumactive);//今日活跃用户数量
        Long yesterdayNumactive = queryUserCount(myYesterday, 0, "num_active");// 今日新增用户数量
        vo.setActiveUsersTodayRate(ComputeUtil.computeRate(todayNumactive,yesterdayNumactive));//今日活跃用户涨跌率
        return vo;
    }

    /**
     * 累计用户数 queryNumRegistered
     */
    public Long queryNumRegistered(){
        //方式一：
       /* QueryWrapper<AnalysisByDay> queryWrapper = new QueryWrapper<>();
        AnalysisByDay aa = getOne(queryWrapper.select("SUM(num_registered) as numRegistered"));*/

        //方式二：
        AnalysisByDay analysisByDay = getOne(Wrappers.<AnalysisByDay>query().select("SUM(num_registered) as numRegistered"));
        return Long.valueOf(analysisByDay.getNumRegistered());
    }

    /**
     * 公共查询统计数量方法
     * today:今日时间
     * offset：开始时间 通过today-offset=得到开始时间
     * column：查询字段
     *
     * sql:select sum(xx) from table  where record_date <= '2021-08-17' and record_date>='2021-08-17'
     */
    public Long queryUserCount(DateTime today,int offset,String column){
        QueryWrapper<AnalysisByDay> queryWrapper = new QueryWrapper<>();
        //添加 where record_date <= '2021-08-18' and record_date>=xxx
        queryWrapper.le("record_date",today.toDateStr());
        queryWrapper.ge("record_date", ComputeUtil.offsetDay(today,offset));
        AnalysisByDay analysisByDay =
                getOne(queryWrapper.select("SUM("+column+") as numRegistered"));
        return Long.valueOf(analysisByDay.getNumRegistered());
    }


    /**
     * 新增、活跃用户、次日留存率
     */
    public AnalysisUsersVo queryAnalysisUsersVo(Long sd, Long ed, Integer type) {

        DateTime startDate = DateUtil.date(sd);

        DateTime endDate = DateUtil.date(ed);

        AnalysisUsersVo analysisUsersVo = new AnalysisUsersVo();

        //今年数据
        analysisUsersVo.setThisYear(this.queryDataPointVos(startDate, endDate, type));
        //去年数据
        analysisUsersVo.setLastYear(this.queryDataPointVos(
                DateUtil.offset(startDate, DateField.YEAR, -1),
                DateUtil.offset(endDate, DateField.YEAR, -1), type)
        );

        return analysisUsersVo;
    }

    private List<DataPointVo> queryDataPointVos(DateTime sd, DateTime ed, Integer type) {

        String startDate = sd.toDateStr();

        String endDate = ed.toDateStr();

        String column = null;
        switch (type) { //101 新增 102 活跃用户 103 次日留存率
            case 101:
                column = "num_registered";
                break;
            case 102:
                column = "num_active";
                break;
            case 103:
                column = "num_retention1d";
                break;
            default:
                column = "num_active";
                break;
        }

        List<AnalysisByDay> analysisByDayList = super.list(Wrappers.<AnalysisByDay>query()
                .select("record_date , " + column + " as num_active")
                .ge("record_date", startDate)
                .le("record_date", endDate));

        return analysisByDayList.stream()
                .map(analysisByDay -> new DataPointVo(DateUtil.date(analysisByDay.getRecordDate()).toDateStr(), analysisByDay.getNumActive().longValue()))
                .collect(Collectors.toList());
    }

}
